﻿/**
 * 主窗口类的构造方法。
 */
function MainWindow() {
    const mButtonAddFriend = document.getElementById("IDC_BUTTON_ADD_FRIEND")           // "添加好友"按钮
    const mButtonLogoff = document.getElementById("IDC_BUTTON_LOGOFF")                  // "离线"按钮
    const mButtonLogon = document.getElementById("IDC_BUTTON_LOGON")                    // "登录"按钮
    const mButtonMChat = document.getElementById("IDC_BUTTON_MCHAT")                    // "群发消息"按钮
    const mButtonReg = document.getElementById("IDC_BUTTON_REG")                        // "注册"按钮
    const mChats = new Map()                                                            // 聊天窗口集合
    var mClient = null                                                                  // 客户端
    const mLabelFriendCount = document.getElementById("IDC_LABEL_FRIEND_COUNT")         // "好友数"标签
    const mLabelStatus = document.getElementById("IDC_LABEL_STATUS")                    // "登录状态"标签
    const mMainWindow = document.getElementById("IDC_MAIN_WINDOW")                      // 主窗口
    const mListViewUsers = new UserListView(false, true, mMainWindow, Const.USER_LIST_VIEW_WIDTH, 
        Const.USER_LIST_VIEW_HEIGHT, Const.USER_LIST_VIEW_X, Const.USER_LIST_VIEW_Y)    // 好友列表控件

    // 设置标题
    document.title = IDS_APP_NAME[LANG]

    // 设置"添加好友"按钮
    mButtonAddFriend.disabled = true
    mButtonAddFriend.onclick = onButtonAddFriendClicked
    mButtonAddFriend.onmousedown = onButtonAddFriendMouseDown
    mButtonAddFriend.onmouseup = onButtonAddFriendMouseUp
    mButtonAddFriend.onmouseout = onButtonAddFriendMouseUp
    setTooltip(mButtonAddFriend, IDS_ADD_FRIEND[LANG])

    // 设置"注销"按钮
    mButtonLogoff.disabled = true
    mButtonLogoff.onclick = onButtonLogoffClicked
    mButtonLogoff.onmousedown = onButtonLogoffMouseDown
    mButtonLogoff.onmouseup = onButtonLogoffMouseUp
    mButtonLogoff.onmouseout = onButtonLogoffMouseUp
    setTooltip(mButtonLogoff, IDS_LOGOFF[LANG])

    // 设置"登录"按钮
    mButtonLogon.onclick = onButtonLogonClicked
    mButtonLogon.onmousedown = onButtonLogonMouseDown
    mButtonLogon.onmouseup = onButtonLogonMouseUp
    mButtonLogon.onmouseout = onButtonLogonMouseUp
    setTooltip(mButtonLogon, IDS_LOGON[LANG])

    // 设置"群发消息"按钮
    mButtonMChat.disabled = true
    mButtonMChat.onclick = onButtonMChatClicked
    mButtonMChat.onmousedown = onButtonMChatMouseDown
    mButtonMChat.onmouseup = onButtonMChatMouseUp
    mButtonMChat.onmouseout = onButtonMChatMouseUp
    setTooltip(mButtonMChat, IDS_MCHAT[LANG])

    // 设置"注册"按钮
    mButtonReg.onclick = onButtonRegClicked
    mButtonReg.onmousedown = onButtonRegMouseDown
    mButtonReg.onmouseup = onButtonRegMouseUp
    mButtonReg.onmouseout = onButtonRegMouseUp
    setTooltip(mButtonReg, IDS_REG[LANG])

    // "好友数"标签
    mLabelFriendCount.innerHTML = IDS_FRIEND_COUNT[LANG].replace("%d", 0)

    // "状态"标签
    mLabelStatus.innerHTML = IDS_STATUS_LOGOFF[LANG]

    // 设置好友列表控件
    mListViewUsers.ondblclick = onListFriendsDoubleClicked

    // 订阅事件
    document.addEventListener(Const.UM_CONNECTED, onConnected)
    document.addEventListener(Const.UM_GET_ADD_FRIEND_REQUEST, onGetAddFriendRequest)
    document.addEventListener(Const.UM_GET_ADD_FRIEND_RESULT, onGetAddFriendResult)
    document.addEventListener(Const.UM_CHAT_C2S, onChatC2S)
    document.addEventListener(Const.UM_CHAT_S2C, onChatS2C)
    document.addEventListener(Const.UM_GET_LOGON_RESULT, onGetLogonResult)
    document.addEventListener(Const.UM_GET_REG_RESULT, onGetRegResult)
    document.addEventListener(Const.UM_FRIEND_LOGOFF, onFriendLogoff)
    document.addEventListener(Const.UM_FRIEND_LOGON, onFriendLogon)

    // 创建客户端
    mClient = new Client()


    /**
     * 添加所有好友到好友列表控件中。
     * @param result    登录结果
     */
    function addAllFriends(result) {
        for (var i = 0; i < result.mFriendCount; i++) {
            addOneFriend(result.mfriendNames[i], result.mfriendIconIndexs[i], result.mFriendsOnline[i])
        }

        mLabelFriendCount.innerHTML = IDS_FRIEND_COUNT[LANG].replace("%d", result.mFriendCount)
    }
    
    /**
     * 添加一个好友到好友列表控件中。
     * @param friendName    好友名
     * @param iconIndex     好友头像索引
     * @param isOnline      好友在线则为 true，否则为 false
     */
    function addOneFriend(friendName, iconIndex, isOnline) {
        if (iconIndex < 0) {
            return
        }
        mListViewUsers.addItem_icon_text(iconIndex, friendName, isOnline)
    }

    /**
     * 改变界面状态。
     * @param isLogon   已登录则为 true，否则为 false
     */
    function changeState(isLogon) {
        mButtonLogon.disabled = isLogon
        mButtonReg.disabled = isLogon
        mButtonAddFriend.disabled = !isLogon
        mButtonMChat.disabled = !isLogon
        mButtonLogoff.disabled = !isLogon

        if (isLogon) {
            mLabelStatus.innerHTML = IDS_STATUS_LOGON[LANG]
            mButtonLogon.style.backgroundImage = Const.BUTTON_LOGON_DISABLED_IMAGE_PATH
            mButtonReg.style.backgroundImage = Const.BUTTON_REG_DISABLED_IMAGE_PATH
            mButtonAddFriend.style.backgroundImage = Const.BUTTON_ADD_FRIEND_IMAGE_PATH
            mButtonMChat.style.backgroundImage = Const.BUTTON_MCHAT_IMAGE_PATH
            mButtonLogoff.style.backgroundImage = Const.BUTTON_LOGOFF_IMAGE_PATH
        } else {
            mLabelStatus.innerHTML = IDS_STATUS_LOGOFF[LANG]
            mButtonLogon.style.backgroundImage = Const.BUTTON_LOGON_IMAGE_PATH
            mButtonReg.style.backgroundImage = Const.BUTTON_REG_IMAGE_PATH
            mButtonAddFriend.style.backgroundImage = Const.BUTTON_ADD_FRIEND_DISABLED_IMAGE_PATH
            mButtonMChat.style.backgroundImage = Const.BUTTON_MCHAT_DISABLED_IMAGE_PATH
            mButtonLogoff.style.backgroundImage = Const.BUTTON_LOGOFF_DISABLED_IMAGE_PATH
        }
        mLabelFriendCount.innerHTML = IDS_FRIEND_COUNT[LANG].replace("%d", 0)
    }

    /**
     * 清除所有聊天窗口。
     */
    function clearChatWindow() {
        mChats.forEach(function (value, key) {
            value.hide()
        }) 
        mChats.clear()
    }

    /**
     * 获取指定好友名对应的聊天窗口。
     * @param friendName    好友名
     * @return 好友名对应的聊天窗口
     */
    function getChatWindow(friendName) {
        // 查找用户名对应的聊天窗口
        var window = mChats.get(friendName)

        // 如果未找到，则新建一个
        if (window == null) {
            window = new ChatWindow(mMainWindow, friendName)
            mChats.set(friendName, window)
        }

        return window
    }

    /**
     * 获取结果信息。
     * @param resultCode    结果码
     * @return 结果信息
     */
    function getResultMessage(resultCode) {
        switch (resultCode) {
            case ResultCode.ADD_FRIEND_ALLOW:
                return IDS_ADD_FRIEND_ALLOW[LANG]
            case ResultCode.ADD_FRIEND_NOT_ALLOW:
                return IDS_ADD_FRIEND_NOT_ALLOW[LANG]
            case ResultCode.ALREADY_BE_FRIENDS:
                return IDS_ALREADY_BE_FRIENDS[LANG]
            case ResultCode.FRIEND_NAME_EQUAL_SELF_NAME:
                return IDS_FRIEND_NAME_EQUAL_SELF_NAME[LANG]
            case ResultCode.LOGON_SUCCEEDED:
                return IDS_LOGON_SUCCEEDED[LANG]
            case ResultCode.NETWORK_ERROR:
                return IDS_NETWORK_ERROR[LANG]
            case ResultCode.PASSWORD_WRONG:
                return IDS_PASSWORD_WRONG[LANG]
            case ResultCode.REG_SUCCEEDED:
                return IDS_REG_SUCCEEDED[LANG]
            case ResultCode.TOO_MANY_FRIENDS:
                return IDS_TOO_MANY_FRIENDS[LANG]
            case ResultCode.USER_ALREADY_LOGON:
                return IDS_USER_ALREADY_LOGON[LANG]
            case ResultCode.USER_EXISTS:
                return IDS_USER_EXISTS[LANG]
            case ResultCode.USER_NOT_FOUND:
                return IDS_USER_NOT_FOUND[LANG]
        }

        return "" 
    }

    /**
     * "添加好友"按钮的单击响应方法。
     */
    function onButtonAddFriendClicked() {
        if (mButtonAddFriend.disabled) {
            return
        }

        // 显示输入窗口，让用户输入好友名
        const username = InputBox.getStringValue("", IDS_PLEASE_INPUT_USERNAME[LANG])
        if (username == null || username == "") {
            return
        }

        // 执行添加好友
        const resultCode = mClient.addFriend(username)
        if (resultCode != ResultCode.SUCCEEDED) {
            toast(mMainWindow, getResultMessage(resultCode))
        }
    }

    /**
     * "添加好友"按钮的鼠标左键按下事件的响应方法。
     */
    function onButtonAddFriendMouseDown() {
        if (mButtonAddFriend.disabled) {
            return
        }
        mButtonAddFriend.style.backgroundImage = Const.BUTTON_ADD_FRIEND_PRESSED_IMAGE_PATH
    }

    /**
     * "添加好友"按钮的鼠标左键抬起事件的响应方法。
     */
    function onButtonAddFriendMouseUp() {
        if (mButtonAddFriend.disabled) {
            return
        }
        mButtonAddFriend.style.backgroundImage = Const.BUTTON_ADD_FRIEND_IMAGE_PATH
    }

    /**
     * "离线"按钮的单击响应方法。
     */
    function onButtonLogoffClicked() {
        if (mButtonLogoff.disabled) {
            return
        }

        // 设置各种控件的状态
        changeState(false)

        // 清空各种列表
        mListViewUsers.clear()
        clearChatWindow()

        // 发送离线请求
        mClient.logoff()
    }

    /**
     * "离线"按钮的鼠标左键按下事件的响应方法。
     */
    function onButtonLogoffMouseDown() {
        if (mButtonLogoff.disabled) {
            return
        }
        mButtonLogoff.style.backgroundImage = Const.BUTTON_LOGOFF_PRESSED_IMAGE_PATH
    }

    /**
     * "离线"按钮的鼠标左键抬起事件的响应方法。
     */
    function onButtonLogoffMouseUp() {
        if (mButtonLogoff.disabled) {
            return
        }
        mButtonLogoff.style.backgroundImage = Const.BUTTON_LOGOFF_IMAGE_PATH
    }

    /**
     * "登录"按钮的单击响应方法。
     */
    function onButtonLogonClicked() {
        if (mButtonLogon.disabled) {
            return
        }
        // 显示登录窗口
        new LogonWindow(onLogonWindowOK, mMainWindow)
    }

    /**
     * "登录"的鼠标左键按下事件的响应方法。
     */
    function onButtonLogonMouseDown() {
        if (mButtonLogon.disabled) {
            return
        }
        mButtonLogon.style.backgroundImage = Const.BUTTON_LOGON_PRESSED_IMAGE_PATH
    }

    /**
     * "登录"的鼠标左键抬起事件的响应方法。
     */
    function onButtonLogonMouseUp() {
        if (mButtonLogon.disabled) {
            return
        }
        mButtonLogon.style.backgroundImage = Const.BUTTON_LOGON_IMAGE_PATH
    }

    /**
     * "群发消息"按钮的单击响应方法。
     */
    function onButtonMChatClicked() {
        if (mButtonMChat.disabled) {
            return
        }
        getChatWindow(MULTI_CHAT).show()
    }

    /**
     * "群发消息"按钮的鼠标左键按下事件的响应方法。
     */
    function onButtonMChatMouseDown() {
        if (mButtonMChat.disabled) {
            return
        }
        mButtonMChat.style.backgroundImage = Const.BUTTON_MCHAT_PRESSED_IMAGE_PATH
    }

    /**
     * "群发消息"按钮的鼠标左键抬起事件的响应方法。
     */
    function onButtonMChatMouseUp() {
        if (mButtonMChat.disabled) {
            return
        }
        mButtonMChat.style.backgroundImage = Const.BUTTON_MCHAT_IMAGE_PATH
    }

    /**
     * “注册”按钮的单击响应方法。
     */
    function onButtonRegClicked() {
        if (mButtonReg.disabled) {
            return
        }
        new RegWindow(onRegWindowOK, mMainWindow)
    }

    /**
     * “注册”按钮的鼠标左键按下事件的响应方法。
     */
    function onButtonRegMouseDown() {
        if (mButtonReg.disabled) {
            return
        }
        mButtonReg.style.backgroundImage = Const.BUTTON_REG_PRESSED_IMAGE_PATH
    }

    /**
     * “注册”按钮的鼠标左键抬起事件的响应方法。
     */
    function onButtonRegMouseUp() {
        if (mButtonReg.disabled) {
            return
        }
        mButtonReg.style.backgroundImage = Const.BUTTON_REG_IMAGE_PATH
    }

    /**
     * 聊天事件的响应方法（客户端到服务器）。
     * @param e 事件相关信息
     */
    function onChatC2S(e) {
        mClient.chat(e.arg1)
    }

    /**
     * 聊天事件的响应方法（服务器到客户端）。
     * @param e 事件相关信息
     */
    function onChatS2C(e) {
        const chatInfo = e.arg1
        var chatWindow = null
        if (chatInfo.mDstUsername == MULTI_CHAT) {
            chatWindow = getChatWindow(MULTI_CHAT)
        } else {
            chatWindow = getChatWindow(chatInfo.mSrcUsername)
        }
        chatWindow.setContent(chatInfo)
        chatWindow.show()
    }

    /**
     * 网络连接完成事件的响应方法。
     * @param e 事件相关信息
     */
    function onConnected(e) {
        const result = e.arg1
        if (!result) {
            // 弹出提示
            window.alert(IDS_NETWORK_ERROR[LANG])
            window.close()
        }
    }

    /**
     * 好友离线事件的响应方法。
     * @param e 事件相关信息
     */
    function onFriendLogoff(e) {
        mListViewUsers.changeItemColor(e.arg1.mUsername, false)
    }

    /**
     * 好友登录事件的响应方法。
     * @param e 事件相关信息
     */
    function onFriendLogon(e) {
        mListViewUsers.changeItemColor(e.arg1.mUsername, true)
    }

    /**
     * 得到添加好友请求事件的响应方法。
     * @param e 事件相关信息
     */
    function onGetAddFriendRequest(e) {
        const request = e.arg1
        const text = request.mSrcUsername + IDS_CONFIRM_ADD_FRIEND[LANG]
        const allow = window.confirm(text)
        mClient.allowAddFriend(allow, request)
        if (allow) {
            addOneFriend(request.mSrcUsername, request.mSrcIconIndex, true)
            mLabelFriendCount.innerHTML = IDS_FRIEND_COUNT[LANG].replace("%d", mClient.getFriendCount())
        }
    }

    /**
     * 得到添加好友结果事件的响应方法。
     * @param e 事件相关信息
     */
    function onGetAddFriendResult(e) {
        const result = e.arg1
        const resultCode = result.mResultCode
        var message = getResultMessage(resultCode)
        if (resultCode == ResultCode.ADD_FRIEND_ALLOW) {
            addOneFriend(result.mDstUsername, result.mDstIconIndex, true)
            mLabelFriendCount.innerHTML = IDS_FRIEND_COUNT[LANG].replace("%d", mClient.getFriendCount())
            message = message.replace("%s", result.mDstUsername)
            toast(mMainWindow, message)
        } else if (resultCode == ResultCode.ALREADY_BE_FRIENDS ||
            resultCode == ResultCode.ADD_FRIEND_NOT_ALLOW ||
            resultCode == ResultCode.USER_NOT_FOUND) {
            message = result.mDstUsername + message
            toast(mMainWindow, message)
        }
    }

    /**
     * 得到登录结果事件的响应方法。
     * @param e 事件相关信息
     */
    function onGetLogonResult(e) {
        const result = e.arg1
        if (result.mResultCode == ResultCode.LOGON_SUCCEEDED) {
            changeState(true)
            addAllFriends(result)
        } else {
            const message = getResultMessage(result.mResultCode)
            toast(mMainWindow, message)
        }
    }

    /**
     * 得到注册结果事件的响应方法。
     * @param e 事件相关信息
     */
    function onGetRegResult(e) {
        const result = e.arg1
        const message = getResultMessage(result.mResultCode)
        toast(mMainWindow, message)
        if (result.mResultCode == ResultCode.REG_SUCCEEDED) {
            changeState(true)
        }
    }

    /**
     * 双击好友列表中某个表项的响应方法。
     */
    function onListFriendsDoubleClicked() {
        const friendName = mListViewUsers.getSelectedItemText()
        const chatWindow = getChatWindow(friendName)
        if (chatWindow != null) {
            chatWindow.show()
        }
    }

    /**
     * 登录窗口的"确定"的单击响应方法。
     * @param logonWindow   登录窗口
     */
    function onLogonWindowOK(logonWindow) {
        if (logonWindow.getClickedButton() == LogonWindowButton.OK) {
            mClient.logon(logonWindow.getUsername(), logonWindow.getPassword())
        }
    }

    /**
     * 注册窗口的"确定"按钮的单击响应方法。
     * @param regWindow 注册窗口
     */
    function onRegWindowOK(regWindow) {
        if (regWindow.getClickedButton() == RegWindowButton.OK) {
            mClient.reg(regWindow.getUsername(), regWindow.getPassword(), regWindow.getIconIndex())
        }
    }

    /**
     * 窗口关闭事件的响应方法。
     */
    window.onbeforeunload = function() {
        // 关闭客户端
        mClient.close()
    }
}
